package com.gitee.dolt.sms.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.*;
import com.gitee.dolt.core.util.SpringUtils;
import com.gitee.dolt.sms.entity.*;
import com.gitee.dolt.sms.enumeration.SmsTemplateStatus;
import com.gitee.dolt.sms.enumeration.SmsTemplateType;
import com.gitee.dolt.sms.event.SmsSendLogEvent;
import com.gitee.dolt.sms.exception.SmsException;
import com.gitee.dolt.sms.properties.SmsProperties;
import com.gitee.dolt.sms.enumeration.SmsType;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author LYH
 */
@RequiredArgsConstructor
@Slf4j
public class AliSmsService implements SmsService<AliSmsRequest, AliBatchSmsRequest> {

    private final Client client;

    private final SmsProperties smsProperties;

    @Override
    public SmsTemplateData querySmsTemplate(String templateCode) {
        QuerySmsTemplateRequest querySmsTemplateRequest = new QuerySmsTemplateRequest();
        querySmsTemplateRequest.setTemplateCode(templateCode);
        try {
            QuerySmsTemplateResponse querySmsTemplateResponse = client.querySmsTemplate(querySmsTemplateRequest);
            QuerySmsTemplateResponseBody querySmsTemplateResponseBody = querySmsTemplateResponse.getBody();
            return transToSmsTemplateData(querySmsTemplateResponseBody);
        } catch (Exception e) {
            throw new SmsException(e.getMessage());
        }
    }


    @Override
    public boolean sendSms(AliSmsRequest aliSmsRequest) {
        SendSmsRequest request = new SendSmsRequest();
        setSingleSmsParams(request, aliSmsRequest);
        SmsSendLogDTO smsSendLogDTO = getSmsSendLogDTO(request);
        try {
            SendSmsResponse sendSmsResponse = client.sendSms(request);
            smsSendLogDTO = setSmsSendLogDTO(smsSendLogDTO, sendSmsResponse);
        } catch (Exception e) {
            smsSendLogDTO.setSuccess(false).setMessage(e.getMessage());
        }
        SpringUtils.publishEvent(new SmsSendLogEvent(smsSendLogDTO));
        return smsSendLogDTO.getSuccess();
    }

    @Override
    public boolean sendBatchSms(AliBatchSmsRequest aliBatchSmsRequest) {
        SendBatchSmsRequest request = new SendBatchSmsRequest();
        setMultiSmsParams(request, aliBatchSmsRequest);
        SmsSendLogDTO smsSendLogDTO = getSmsSendLogDTO(request);
        try {
            SendBatchSmsResponse sendBatchSmsResponse = client.sendBatchSms(request);
            smsSendLogDTO = setSmsSendLogDTO(smsSendLogDTO, sendBatchSmsResponse);
            return true;
        } catch (Exception e) {
            smsSendLogDTO.setSuccess(false).setMessage(e.getMessage());
        }
        SpringUtils.publishEvent(new SmsSendLogEvent(smsSendLogDTO));
        return smsSendLogDTO.getSuccess();
    }

    private SmsSendLogDTO setSmsSendLogDTO(SmsSendLogDTO smsSendLogDTO, SendSmsResponse sendSmsResponse) {
        SendSmsResponseBody body = sendSmsResponse.getBody();
        smsSendLogDTO.setSuccess("OK".equals(body.getCode()))
                .setCode(body.getCode())
                .setMessage(body.getMessage())
                .setRequestId(body.getRequestId())
                .setSentDate(LocalDateTime.now())
                .setBizId(body.getBizId());
        return smsSendLogDTO;
    }

    private SmsSendLogDTO setSmsSendLogDTO(SmsSendLogDTO smsSendLogDTO, SendBatchSmsResponse sendBatchSmsResponse) {
        SendBatchSmsResponseBody body = sendBatchSmsResponse.getBody();
        smsSendLogDTO.setSuccess("OK".equals(body.getCode()))
                .setCode(body.getCode())
                .setMessage(body.getMessage())
                .setRequestId(body.getRequestId())
                .setSentDate(LocalDateTime.now())
                .setBizId(body.getBizId());
        return smsSendLogDTO;
    }

    private SmsSendLogDTO getSmsSendLogDTO(SendSmsRequest sendSmsRequest) {
        String templateParam = sendSmsRequest.getTemplateParam();
        SmsSendLogDTO smsSendLogDTO = new SmsSendLogDTO();
        smsSendLogDTO.setTemplateId(sendSmsRequest.getTemplateCode()).setSmsType(SmsType.ALI)
                .setPhoneNumbers(sendSmsRequest.getPhoneNumbers())
                .setSignName(sendSmsRequest.getSignName())
                .setParams(templateParam).setBatch(false).setBeginDate(LocalDateTime.now());
        return smsSendLogDTO;
    }

    private SmsSendLogDTO getSmsSendLogDTO(SendBatchSmsRequest sendBatchSmsRequest) {
        SmsSendLogDTO smsSendLogDTO = new SmsSendLogDTO();
        smsSendLogDTO.setTemplateId(sendBatchSmsRequest.getTemplateCode()).setSmsType(SmsType.ALI)
                .setPhoneNumbers(sendBatchSmsRequest.getPhoneNumberJson())
                .setSignName(sendBatchSmsRequest.getSignNameJson())
                .setParams(sendBatchSmsRequest.getTemplateParamJson()).setBatch(true).setBeginDate(LocalDateTime.now());
        return smsSendLogDTO;
    }

    private void setMultiSmsParams(SendBatchSmsRequest request, AliBatchSmsRequest aliBatchSmsRequest) {
        String templateCode = aliBatchSmsRequest.getTemplateCode();
        List<AliBatchSmsObj> smsObjs = aliBatchSmsRequest.getSmsObjs();
        if (StrUtil.isEmpty(templateCode)) {
            throw new IllegalArgumentException("param templateCode can not be empty");
        }
        List<String> phoneNumbers = new ArrayList<>();
        List<String> signNames = new ArrayList<>();
        List<String> smsUpExtendCodes = new ArrayList<>();
        List<Map<String, String>> templateParams = new ArrayList<>();
        smsObjs.forEach(smsObj -> {
            String phoneNumber = smsObj.getPhoneNumber();
            String signName = StrUtil.emptyToDefault(smsObj.getSignName(), smsProperties.getSignName());
            String smsUpExtendCode = smsObj.getSmsUpExtendCode();
            Map<String, String> templateParam = smsObj.getTemplateParam();
            if (StrUtil.isEmpty(phoneNumber)) {
                throw new IllegalArgumentException("param phoneNumber can not be empty");
            }
            if (StrUtil.isEmpty(signName)) {
                throw new IllegalArgumentException("param signName can not be empty");
            }
            phoneNumbers.add(phoneNumber);
            signNames.add(signName);
            smsUpExtendCodes.add(smsUpExtendCode);
            templateParams.add(templateParam);
            smsObj.setSignName(signName);
        });
        request.setPhoneNumberJson(JSONUtil.toJsonStr(phoneNumbers));
        request.setSignNameJson(JSONUtil.toJsonStr(signNames));
        request.setSmsUpExtendCodeJson(JSONUtil.toJsonStr(smsUpExtendCodes));
        request.setTemplateParamJson(JSONUtil.toJsonStr(templateParams));
    }

    private void setSingleSmsParams(SendSmsRequest request, AliSmsRequest aliSmsRequest) {
        String templateCode = aliSmsRequest.getTemplateCode();
        String[] phoneNumbers = aliSmsRequest.getPhoneNumbers();
        String signName = StrUtil.emptyToDefault(aliSmsRequest.getSignName(), smsProperties.getSignName());
        if (StrUtil.isEmpty(templateCode)) {
            throw new IllegalArgumentException("param templateCode can not be empty");
        }
        if (ArrayUtil.isEmpty(phoneNumbers)) {
            throw new IllegalArgumentException("param phoneNumbers can not be empty");
        }
        if (ArrayUtil.isEmpty(signName)) {
            throw new IllegalArgumentException("param signName can not be empty");
        }
        request.setTemplateCode(templateCode);
        request.setPhoneNumbers(ArrayUtil.join(phoneNumbers, StrUtil.COMMA));
        request.setSignName(signName);
        request.setTemplateParam(JSONUtil.toJsonStr(aliSmsRequest.getTemplateParam()));
        request.setSmsUpExtendCode(aliSmsRequest.getSmsUpExtendCode());
        request.setOutId(aliSmsRequest.getOutId());
        aliSmsRequest.setSignName(signName);
    }

    private SmsTemplateData transToSmsTemplateData(QuerySmsTemplateResponseBody body) {
        Integer templateStatus = body.getTemplateStatus();
        Integer templateType = body.getTemplateType();
        SmsTemplateStatus smsTemplateStatus = null;
        SmsTemplateType smsTemplateType = null;
        if (templateStatus != null) {
            if (templateStatus == 0) {
                smsTemplateStatus = SmsTemplateStatus.UNDER_REVIEW;
            } else if (templateStatus == 1) {
                smsTemplateStatus = SmsTemplateStatus.APPROVED;
            } else if (templateStatus == 2) {
                smsTemplateStatus = SmsTemplateStatus.AUDIT_FAILED;
            }
        }
        if (templateType != null) {
            if (templateType == 0) {
                smsTemplateType = SmsTemplateType.VERIFICATION_CODE;
            } else if (templateType == 1) {
                smsTemplateType = SmsTemplateType.SMS_NOTIFICATION;
            } else if (templateType == 2) {
                smsTemplateType = SmsTemplateType.PROMOTING_SMS;
            } else if (templateType == 3) {
                smsTemplateType = SmsTemplateType.INTERNATIONAL_MSG;
            }
        }
        return new SmsTemplateData().setCreateDate(DateUtil.parseLocalDateTime(body.getCreateDate()))
                .setReason(body.getReason()).setTemplateCode(body.getTemplateCode())
                .setTemplateContent(body.getTemplateContent()).setTemplateName(body.getTemplateName())
                .setTemplateStatus(smsTemplateStatus).setTemplateType(smsTemplateType)
                .setCode(body.getCode()).setMessage(body.getMessage()).setRequestId(body.getRequestId());
    }


}
